/*
 * dua.c - dutils - EBC tool
 * Clunix, cezanne@clunix.com, 2009.5
 *
 * Copyright (c) 2001-2008 by Clunix Inc. All Rights Reserved.
 */
#include "config.h"

#include "dua.h"

ebc_t	*ec;

static const char	*serverip;
static ecm_uint16	ebc_port = EBC_PORT_DEF;

static ecm_strlist_t	dushd_modlist;
static ecm_strlist_t	excluded_list;
static ecm_uint32	dush_timeout = 60000;

static char	*src_path, *dst_path;
static dush_fileopt_t	fileopt;

static dua_type_t	dua_type = 0;

void
dua_usage(void)
{
	ecm_fprintf(ecm_stderr,
"Usage: dua [ <options> ] <dua type dependent args>\n"
" Options:\n"
"   -s <dushd ebc server ip>\n" 
"   -p <ebc port>\n"
"   -m <dushd module name>: can be specified multiple times\n"
"   -x <exclueded modules>: can be specified multiple times\n"
"   -t <timeout in secs>\n"
"   -x <exclueded modules>: can be specified multiple times\n"
"   -f : forcefully\n"
" Dua Type Dependent Arguments:\n"
"    -u <src path> <dst path>: upload file(default)\n"
"    -d <dst path>: delete file\n"
"\n"
" Environment Variables:\n"
"    EBC_PORT: default ebc port\n"
"    DUSH_EBCD_SERVER: ebcd server ip\n"
"    DUSH_TIMEOUT: execution time limit in seconds\n"
" dushd module list: '.nodelist' in current directory\n"
		);
}

static void
parse_args(int argc, char *argv[])
{
	int	c;
	int	errflag = 0;

	while ((c = ecm_getopt(argc, argv, "s:p:m:x:t:udfh:")) != -1) {
		switch(c) {
		case 's':
			serverip = ecm_strdup(ecm_optarg);
			break;
		case 'p':
			if (ecm_sscanf(ecm_optarg, "%hu", &ebc_port) != 1)
				errflag++;
			break;
		case 'm':
			if (dushd_modlist == NULL) {
				dushd_modlist = ecm_strlist_create(ECM_FALSE);
			}
			ecm_strlist_add(dushd_modlist, ecm_optarg);
			break;
		case 'x':
			if (excluded_list == NULL) {
				excluded_list = ecm_strlist_create(ECM_FALSE);
			}
			ecm_strlist_add(excluded_list, ecm_optarg);
			break;
		case 't':
			if (ecm_sscanf(ecm_optarg, "%u", &dush_timeout) != 1)
				errflag++;
			break;
		case 'u':
			if (dua_type != 0) {
				ecm_fprintf(ecm_stderr, "multiple dua types\n");
				errflag++;
			}
			else
				dua_type = DUA_UPLOAD;
			break;
		case 'd':
			if (dua_type != 0) {
				ecm_fprintf(ecm_stderr, "multiple dua types\n");
				errflag++;
			}
			else
				dua_type = DUA_DELETE;
			break;
		case 'f':
			fileopt |= DUSH_FILEOPT_FORCE;
			break;
		case 'h':
			dua_usage();
			exit(0);
			break;
		default: 
			errflag++;
			break;
		}
	}

	if (errflag || ecm_optind >= argc) {
		dua_usage();
		exit(1);
	}

	if (dua_type == 0)
		dua_type = DUA_UPLOAD;

	switch (dua_type) {
		case DUA_UPLOAD:
			if (argc - ecm_optind < 2) {
				dua_usage();
			}
			else {
				src_path = argv[ecm_optind];
				dst_path = argv[ecm_optind + 1];
			}
			break;
		case DUA_DELETE:
			if (argc - ecm_optind < 1) {
				dua_usage();
			}
			else {
				dst_path = argv[ecm_optind];
			}
		default:
			break;
	}

	if (ecm_empty_str(serverip))
		serverip = ecm_getenv("DUSH_EBCD_SERVER");
}

static void
file_func(ecm_ptr_t ctx)
{
	const char	*modname = (const char *)ctx;
	dush_err_t	err;

	switch (dua_type) {
	case DUA_UPLOAD:
		err = dua_file_upload(modname, src_path, dst_path, fileopt);
		if (err < 0) {
			printf("%s: can't upload: %d\n", modname, err);
			return;
		}
		break;
	case DUA_DELETE:
		err = dua_file_delete(modname, dst_path, fileopt);
		if (err < 0) {
			printf("%s: can't delete: %d\n", modname, err);
			return;
		}
	}
}

static void
cmd_file(const char *path)
{
	ecm_workers_t	workers;
	const char	*modname;

	workers = ecm_init_workers(0, NULL, NULL, NULL);
	for (modname = ecm_strlist_first(dushd_modlist);
	     modname;
	     modname = ecm_strlist_next(dushd_modlist)) {
		if (ecm_strlist_find(excluded_list, modname) >= 0)
			continue;
		ecm_start_worker(workers, file_func, (ecm_ptr_t)modname);
	}
	ecm_clear_all_workers(workers);
}

static ECMBOOL
setup_dushd_modlist(void)
{
	char	buf[256], *line;
	FILE	*fp;
	
	fp = ecm_fopen(".nodelist", "r");
	if (fp == NULL)
		return ECM_FALSE;
	dushd_modlist = ecm_strlist_create(ECM_FALSE);
	while ((ecm_fgets(buf, sizeof buf, fp))) {
		line = ecm_trim(buf);
		if (*line == '#')
			continue;
		ecm_strlist_add(dushd_modlist, "%s", line);
	}
	return ECM_TRUE;
}

int
main(int argc, char *argv[])
{
	ecm_initialize();

	/* set default ebc_port */
	ecm_sscanf(ecm_getenv(ECM_EBC_PORT_ENV), "%hu", &ebc_port);

	parse_args(argc, argv);

	if (dushd_modlist == NULL && !setup_dushd_modlist()) {
		ecm_fprintf(ecm_stderr, ".nodelist missing");
		return 1;
	}

	if (ebc_connect(serverip, ebc_port, NULL, 5000, (ecm_ebc_t *)&ec) != EBC_OK) {
		fprintf(stderr, "ebc_connect to %hu error\n", ebc_port);
		exit(1);
	}

	cmd_file(argv[ecm_optind]);

	ebc_close(ec);
	return 0;
}
